Skip to content

chore: take over release automation and remove Stainless dependencies#100

Merged
MingruiZhang merged 6 commits into
mainfrom
chore/stainless-exit
Jul 7, 2026
Merged

chore: take over release automation and remove Stainless dependencies#100
MingruiZhang merged 6 commits into
mainfrom
chore/stainless-exit

Conversation

@MingruiZhang

@MingruiZhang MingruiZhang commented Jul 7, 2026

Copy link
Copy Markdown
Member

Context

Stainless sunsets its platform for our account on 2026-09-01. This PR implements Problem 1 (Getting off Stainless) of the design doc — included here as docs/design/stainless-exit-and-v2.md, status Approved.

Today's release pipeline is split: the Stainless GitHub App runs release-please externally (opens release PRs, creates tags + GitHub Releases — every recent release was authored by stainless-app[bot]), while the in-repo publish-pypi.yml already publishes on the release event with our own token. Only the orchestration half dies with the sunset; this PR replaces it.

Changes

  • New .github/workflows/release.yml — one-shot, dispatch-only releases. A maintainer runs the workflow and picks patch / minor / major. The workflow computes the next version from the latest tag, stamps pyproject.toml + _version.py, prepends the changelog section (generated by the new .github/scripts/generate_release_notes.py, grouped by Conventional Commit prefixes in the existing CHANGELOG style), lands the release: x.y.z commit directly on main, tags it, and creates the GitHub Release → publish-pypi.yml → PyPI. No release PR; dispatching is the release decision. Ordinary merges never trigger any of this.
  • release-please fully removed — config, manifest, and the x-release-please-version annotation are gone; changelog + stamping are ~70 lines of owned script.
  • ci.yml — triggers simplified to main + PRs; removed stainless-sdks/* depot-runner conditionals, the pkg.stainless.com artifact upload, and the codegen-metadata skip.
  • Removed .stats.yml and scripts/utils/upload-artifact.sh.
  • CONTRIBUTING.md / SECURITY.md / README — owned-code rewrite; security contact now GitHub private vulnerability reporting / [email protected] (please confirm); dropped "generated with Stainless" and the vscode.stainless.com badge.

Required before this works end-to-end

  1. Create the RELEASE_TOKEN repo secret — fine-grained PAT (or GitHub App token) with Contents: write, whose owner can bypass the main ruleset (main requires PRs; this repo's ruleset grants "always" bypass to organization admins — the release commit uses that bypass). The default GITHUB_TOKEN can't be used: releases it creates don't trigger publish-pypi.yml.
  2. Close the stale bot release PR release: 1.13.0 #90 — nothing replaces it; the next release happens when a maintainer dispatches Release.
  3. On the first dispatch, review the produced release commit + GitHub Release (version, changelog) — that run is the exit-criterion validation.
  4. Once a release publishes end-to-end without Stainless, uninstall the Stainless GitHub App from the org.

🤖 Generated with Claude Code

Stainless (acquired by Anthropic) sunsets its platform for our account on
2026-09-01. This implements Problem 1 of the attached design doc:

- Add self-hosted release-please workflow (replaces the Stainless app,
  which opened release PRs and created tags/GitHub Releases externally)
- Point release-please-config.json $schema at upstream googleapis
- Simplify CI triggers to main + PRs; drop stainless-sdks runner
  conditionals and the pkg.stainless.com artifact upload
- Remove .stats.yml (Stainless codegen metadata)
- Rewrite CONTRIBUTING.md and SECURITY.md for owned, hand-maintained code
- Drop "generated with Stainless" phrasing and the vscode.stainless.com
  MCP badge from README
- Add the approved design doc (docs/design/stainless-exit-and-v2.md)

Co-Authored-By: Claude Fable 5 <[email protected]>
Copilot AI review requested due to automatic review settings July 7, 2026 18:58

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR transitions release orchestration from the external Stainless GitHub App to in-repo GitHub Actions, and removes remaining Stainless-specific metadata and CI steps so releases/publishing continue to work after the Stainless sunset.

Changes:

  • Added a self-hosted release-please workflow on pushes to main, using the existing manifest/config.
  • Simplified CI triggers and removed Stainless-only runner/artifact-upload logic.
  • Cleaned up documentation and removed Stainless metadata/files (.stats.yml, artifact upload script, README/SECURITY/CONTRIBUTING updates) plus added the design doc.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated no comments.

Show a summary per file
File Description
SECURITY.md Updates vulnerability reporting guidance away from Stainless to GitHub reporting + LandingAI support.
scripts/utils/upload-artifact.sh Removes Stainless storage artifact upload script.
release-please-config.json Points schema to the upstream googleapis release-please schema URL.
README.md Removes “generated with Stainless” wording and the VS Code Stainless MCP badge.
docs/design/stainless-exit-and-v2.md Adds the approved design doc describing the Stainless exit and future pipeline direction.
CONTRIBUTING.md Updates contribution guidance to reflect hand-maintained ownership and Conventional Commits for release automation.
.stats.yml Removes Stainless codegen metadata file.
.github/workflows/release-please.yml Adds self-hosted release-please workflow using a repo secret token.
.github/workflows/ci.yml Simplifies triggers/runners and removes Stainless-only conditionals and artifact upload steps.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Per review: ordinary merges to main must never create release PRs.
Releases now start with a maintainer running the Release workflow and
choosing patch/minor/major; the release-please CLI opens a release PR
pinned to exactly that version (changelog and version stamping still
come from the existing config/manifest). Merging that PR triggers the
finalize job, which creates the tag + GitHub Release and thereby the
PyPI publish. Config drops the now-bypassed prerelease versioning keys.

Co-Authored-By: Claude Fable 5 <[email protected]>
@MingruiZhang

Copy link
Copy Markdown
Member Author

Release model revised per Mingrui's feedback: releases are now dispatch-only — a maintainer runs the Release workflow and explicitly picks patch/minor/major; ordinary merges to main never open release PRs. See the updated release.yml and PR description.

🤖 Claude Code

Per review: dispatching the Release workflow IS the release decision, so
the intermediate release PR is gone. The workflow now stamps the version
(pyproject.toml, _version.py), prepends the changelog section, lands the
release commit directly on main (requires the RELEASE_TOKEN owner to
have ruleset bypass), tags it, and creates the GitHub Release that
triggers the PyPI publish. release-please is fully removed (config,
manifest, version annotations) in favor of a small owned script.

Co-Authored-By: Claude Fable 5 <[email protected]>
Copilot AI review requested due to automatic review settings July 7, 2026 22:06
@MingruiZhang

Copy link
Copy Markdown
Member Author

Revised again per feedback: the release PR is gone entirely. Dispatching Release (with an explicit patch/minor/major choice) now stamps versions + changelog, lands the release commit directly on main via ruleset bypass, tags, and publishes — one human action total. release-please is fully removed in favor of a small owned script (smoke-tested against the real commit history). Note the secret is now named RELEASE_TOKEN and its owner must have ruleset bypass (org admin).

🤖 Claude Code

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 12 out of 12 changed files in this pull request and generated 7 comments.

Comment thread src/landingai_ade/_version.py Outdated
Comment thread .github/workflows/release.yml
Comment thread .github/workflows/release.yml
Comment thread .github/workflows/release.yml
Comment thread .github/workflows/release.yml
Comment thread .github/scripts/generate_release_notes.py Outdated
Comment thread .github/scripts/generate_release_notes.py Outdated
MingruiZhang and others added 2 commits July 7, 2026 15:12
Length-sorted imports with future annotations (isort length-sort +
FA102), typed the bucket dict for strict pyright, and replaced print
with sys.stdout.write (T201). Verified locally against the pinned ruff
0.14.13, pyright 1.1.399, and mypy 1.17.0.

Co-Authored-By: Claude Fable 5 <[email protected]>
- Add a concurrency group to the Release workflow so concurrent
  dispatches queue instead of racing the version computation
- Hoist SECTION_KEYS out of the per-commit loop in the notes script
- Drop the Stainless-generated header from _version.py
- Simplify release-doctor to dispatch-only (its PR trigger gated on
  release-please branch names that no longer exist)

Co-Authored-By: Claude Fable 5 <[email protected]>
Copilot AI review requested due to automatic review settings July 7, 2026 22:16

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 13 out of 13 changed files in this pull request and generated 1 comment.

Comment thread .github/workflows/release.yml
Per review: the one-shot release could previously tag and publish
without validating the release commit itself. The workflow now runs
bootstrap + rye build + tests on the stamped tree and aborts — before
any commit, tag, or Release exists — if anything is red.

Co-Authored-By: Claude Fable 5 <[email protected]>
@MingruiZhang

Copy link
Copy Markdown
Member Author

The header sweep promised in the review is up: #101 (and landing-ai/ade-typescript#71 for the TS side), stacked on this branch — they'll retarget to main when this merges.

🤖 Claude Code

@MingruiZhang MingruiZhang merged commit c502fa8 into main Jul 7, 2026
3 checks passed
MingruiZhang added a commit to landing-ai/ade-typescript that referenced this pull request Jul 7, 2026
…#70)

* fix: configure npm OIDC Trusted Publishing correctly

The previous approach installed [email protected] in a ../oidc/ prefix directory
and ran it directly, which didn't properly trigger the OIDC token exchange
for Trusted Publishing authentication.

Changes:
- Upgrade setup-node to v4 with registry-url to configure .npmrc
- Install [email protected] globally instead of in a prefix directory
- Add --provenance and --access public flags to trigger OIDC auth

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>

* build: fetch tsc-multi from npm instead of the Stainless-hosted tarball

package.json pinned tsc-multi to a tarball on the stainless-api GitHub
org's release assets, which goes away when that org is archived after
the Stainless sunset (2026-09-01). @stainless-api/tsc-multi is published
on npm (persists regardless); the bin name is unchanged, so scripts/build
works as before. Verified: full root + mcp-server build, pack, and sign
pass with 1.1.12.

Co-Authored-By: Claude Fable 5 <[email protected]>

* chore: take over release automation and remove Stainless dependencies

Stainless sunsets its platform for our account on 2026-09-01. This
implements Problem 1 of the design doc (landing-ai/ade-python#100):

- Add self-hosted release-please workflow (replaces the Stainless app,
  which opened release PRs and created tags/GitHub Releases externally)
- Point release-please-config.json $schema at upstream googleapis and
  drop the README.md / mcp yarn.lock extra-files (no version strings in
  either; upstream's generic updater would no-op on them)
- Simplify CI triggers to main + PRs; drop stainless-sdks runner
  conditionals and both pkg.stainless.com artifact uploads
- Bump deprecated actions/setup-node (Node 20 action runtimes leave
  GitHub runners 2026-09-16)
- Guard the DXT release-asset upload so manual workflow_dispatch runs
  don't fail on an empty release tag
- Remove .stats.yml and scripts/utils/upload-artifact.sh
- Rewrite CONTRIBUTING.md and SECURITY.md for owned, hand-maintained code
- Drop "generated with Stainless" phrasing and the vscode.stainless.com
  MCP badge from README

Co-Authored-By: Claude Fable 5 <[email protected]>

* chore: trigger CI

* chore: make releases dispatch-only with maintainer-chosen version bump

Per review: ordinary merges to main must never create release PRs.
Releases now start with a maintainer running the Release workflow and
choosing patch/minor/major; the release-please CLI opens a release PR
pinned to exactly that version (changelog and multi-file version
stamping still come from the existing config/manifest). Merging that PR
triggers the finalize job, which creates the tag + GitHub Release and
thereby the npm publish. Config drops the now-bypassed prerelease
versioning keys.

Co-Authored-By: Claude Fable 5 <[email protected]>

* chore: release directly from dispatch — no release PR

Per review: dispatching the Release workflow IS the release decision, so
the intermediate release PR is gone. The workflow now stamps the version
(package.json, src/version.ts, mcp-server package.json + manifest.json),
prepends the changelog section, lands the release commit directly on
main (requires the RELEASE_TOKEN owner to have ruleset bypass), tags it,
and creates the GitHub Release that triggers the npm publish.
release-please is fully removed (config, manifest, version annotations)
in favor of a small owned script.

Co-Authored-By: Claude Fable 5 <[email protected]>

* chore: sync release-notes script lint fixes from ade-python

Keep the shared script byte-identical across both SDK repos.

Co-Authored-By: Claude Fable 5 <[email protected]>

* fix: address Copilot review — release concurrency + cleanups

- Add a concurrency group to the Release workflow so concurrent
  dispatches queue instead of racing the version computation
- Sync the notes-script SECTION_KEYS hoist from ade-python
- Simplify release-doctor to dispatch-only (its PR trigger gated on
  release-please branch names that no longer exist)

Co-Authored-By: Claude Fable 5 <[email protected]>

* fix: gate the release on building and testing the stamped tree

Mirror of the ade-python change: bootstrap + build + tests run on the
stamped tree, aborting the release before any commit or tag exists if
anything is red.

Co-Authored-By: Claude Fable 5 <[email protected]>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
MingruiZhang added a commit that referenced this pull request Jul 7, 2026
The SDK is hand-maintained since the Stainless exit (#100); the
"File generated from our OpenAPI spec by Stainless" headers gave
contributors guidance that contradicts CONTRIBUTING.md. Mechanical
sweep of 34 source files plus the two .keep placeholders.

Co-Authored-By: Claude Fable 5 <[email protected]>
MingruiZhang added a commit that referenced this pull request Jul 8, 2026
The SDK is hand-maintained since the Stainless exit (#100); the
"File generated from our OpenAPI spec by Stainless" headers gave
contributors guidance that contradicts CONTRIBUTING.md. Mechanical
sweep of 34 source files plus the two .keep placeholders.

Co-authored-by: Claude Fable 5 <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants